#After roadRunner.run() executed,
#execute roadRunner.report() show the Performance report

module RoadRunnerModule
  def run
    @strat_time = Time.now
    @initBlk.call
    @thread_pool = {}
    @counter = 0

    @log.debug "Mode => #{@mode}"
    iterationBlk = case @mode
    when /thread/,/t/ then
      proc {      
        @users.times do |userId|
          @thread_pool[Thread.start(){
            @iterations.times do |iterationId|
              rcost = self.transaction('Action',&@actBlk)
              self.log.debug "IterationID is #{self.iterationId};UserID is #{self.userId};This Action Cost #{rcost} seconds"
              @longest = (@longest<rcost)?rcost:@longest
              @thread_pool[Thread.current][:iterationId] = iterationId
            end
            @counter += 1
          }]={:userId=>userId}
        end
  #      @thread_pool.keys.each{|t|t.join}
        while @counter != @users do
          Thread.pass
        end
      }
    when /process/,/p/ then
      proc {
        ppid=Process.pid
        @log.info("Main Process pid => #{ppid}")
        
        pids=[]
        @users.times { |userId|
          pids << Process.fork { 
            @userId=userId
            @iterations.times do |iterationId|
              @iterationId=iterationId
              rcost = self.transaction('Action',&@actBlk)
              @longest = (@longest<rcost)?rcost:@longest
            end
            @log.info("<PID:#{Process.pid}> going down.Longest job cost #{@longest}")
            
            Process.kill("HUP", ppid)
          }
        }
        
        switch=true
        c=0
        Signal.trap("HUP", proc { @log.info("One User(Process) done."); (switch = false;p "Main process<#{Process.pid}> going down.") if ((c+=1) == @users) })
        
        @log.info "Waiting Processes => #{pids.inspect}"
        
        p "Processes<#{pids.inspect}> working."
        while switch
          STDOUT.puts '.'
          sleep 5
        end
        p $/
        
        Process.waitall
        @log.info "Processes down."
      }
    else
      proc {
        @iterations.times do |iterationId|
          @iterationId=iterationId
          @users.times do |userId|
            @userId=userId
            rcost = self.transaction('Action',&@actBlk)
            # => the below sentence cost a lot of system resource
            # => if you run for production result,keep it annotated!!!
  #          self.log.debug "IterationID is #{self.iterationId};UserID is #{self.userId};This Action Cost #{rcost} seconds"
            @longest = (@longest<rcost)?rcost:@longest
          end
        end
      }
    end

    p '      '+"RoadRunner".center(50, '*')
    p '      *'+"---Run , on your way.".rjust(48, ' ')+'*'
    p '      '+'*'*50
    p
    p "      Running......"
    @rep = Benchmark::measure(&iterationBlk)
    p "      Ending......"
    @endBlk.call

    @tps = @iterations*@users/@rep.real
  end
end